package org.libermundi.theorcs.chronicles.tapestry.components.sheet;

import java.awt.image.BufferedImage;
import java.util.List;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.Block;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.AfterRender;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.beaneditor.Validate;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.apache.tapestry5.upload.services.UploadedFile;
import org.libermundi.theorcs.chronicles.model.sheet.Sheet;
import org.libermundi.theorcs.chronicles.model.sheet.SheetContainer;
import org.libermundi.theorcs.chronicles.model.sheet.SheetContainer.ContainerType;
import org.libermundi.theorcs.chronicles.model.sheet.SheetPage;
import org.libermundi.theorcs.chronicles.model.sheet.Skill;
import org.libermundi.theorcs.chronicles.model.sheet.old.SkillBlock;
import org.libermundi.theorcs.core.exceptions.ImageManipulationException;
import org.libermundi.theorcs.core.tapestry.services.AppHelper;
import org.libermundi.theorcs.core.tapestry.services.assets.FileManager;
import org.libermundi.theorcs.core.tapestry.services.assets.FileType;
import org.libermundi.theorcs.core.tapestry.services.assets.OfsFilesUtils;
import org.libermundi.theorcs.core.tapestry.services.assets.OrcsFileSystem;
import org.libermundi.theorcs.core.util.ImageUtils;

import com.google.common.base.Strings;

@Import(library={
	"${core.scripts}/jquery.jeditable.js",
	"${chronicles.scripts}/container.settings.js",
	"${chronicles.scripts}/container.lang.js",
	"${chronicles.scripts}/container.editorhandler.js",
	"${chronicles.scripts}/container.editor.js",
	"${layout.scripts}/bootstrap/bootstrap-modal.js",
	"${layout.scripts}/bootstrap/bootstrap-transition.js"
})
public class ContainerEditor {
	
	@Environmental
	private JavaScriptSupport _jsSupport;

	@Inject 
	private ComponentResources _resources;
	
	@Inject
	private AppHelper _appHelper;
	
	@Inject
	private Block _containerSettingsForm;
	
	@Inject
	private Block _skillContainerEditor;
	
	@Inject
	private Block _imageContainerEditor;
	
	@Inject
	private Block _textContainerEditor;
	
	@Property
	@Persist
	private SheetContainer _currentContainer;
	
	@Inject
	private Block _refresh;
	
	@Property
	private SkillBlock _skillBlock;
	
	@Parameter(allowNull=false,required=true)
	private SheetPage _page;
	
    @Inject
    @OrcsFileSystem
    private FileManager _fileManager;
    
    @Inject
    private Request _request;
    
    @Inject
    @Symbol(SymbolConstants.ASSET_PATH_PREFIX)
    private String _t5AssetPrefix;    
    
    // ~ -------------- Form Management Fields ---------------
	
	@Property
    @Persist
    @Validate("required")
    private ContainerType _containerType;
	
	@Property
	private UploadedFile _image;
	
	@Property(read=false)
	@Persist
	private String _text;
	
	@Property
	private Skill _skill;
	
	// ~ -------------- Render Phase -------------------------
	
	@AfterRender
	public void afterRender(){
		_jsSupport.addScript("ContainerEditorSettings.init('%s');",
									_appHelper.getBaseUrlEventLink(_resources));
		_jsSupport.addScript("ContainerEditorHandler.init();");
	}
	
	// ~ ------------- Getters & Setters ---------------------
	public List<Skill> getSkills(){
		return _currentContainer.getSkills();
	}
	
	public String getText(){
		return _currentContainer.getText();
	}
	
	public ValueEncoder<Skill> getSkillEncoder() {
		return new ValueEncoder<Skill>() {
			@Override
			public String toClient(Skill skill) {
				return skill.getUid();
			}

			@Override
			public Skill toValue(String uid) {
				List<Skill> skills = _currentContainer.getSkills();
				for (Skill skill : skills) {
					if(skill.getUid().equals(uid)){
						return skill;
					}
				}
				return null;
			}
		};
	}
	
	// ~ ------------- Event Management ----------------------
	
	@OnEvent("edittitle")
	public JSONObject editTitle(
			@RequestParameter("uid") String uid,
			@RequestParameter(value="newLabel",allowBlank=true) String newLabel
			) {
		
		if(!Strings.isNullOrEmpty(newLabel)) {
			_page.getContainer(uid).setName(newLabel);
		}
		
		JSONObject result = new JSONObject();
			result.put("newLabel", newLabel);

		return result;
	}

	@OnEvent("editsettings")
	public Block editSettings(
			@RequestParameter("uid") String uid
			) {
		loadContainer(uid);
		return _containerSettingsForm;
	}
	
	@OnEvent("editcontainer")
	public Block editContainer(
			@RequestParameter("uid") String uid
			) {
		loadContainer(uid);
		
		switch(_currentContainer.getType()){
			case SKILLS:
				return _skillContainerEditor;
			case IMAGE:
				return _imageContainerEditor;
			case TEXT:	
				return _textContainerEditor;
			default:
				throw new UnsupportedOperationException();
		}
	}
	
	@OnEvent(value="addRow")
	public Skill addSkill(){
		return _currentContainer.addSkill();
	}
	
	
	
	// ~  ------------- Form Management ----------------------
	@OnEvent(value="success",component="skillsContainerEditForm")
	private Block saveSkills(){
		return _refresh;
	}
	
	@OnEvent(value="success",component="editSettingsForm")
	public Block changeContainerType(){
		return _refresh;
	}
	
	@OnEvent(value="success",component="imageContainerEditForm")
	public void saveContainerImage() {
		if(_image != null){
			try {
				Asset savedAsset = _fileManager.save(_image,FileType.IMAGE);
				BufferedImage savedImage = ImageUtils.loadImage(savedAsset.getResource().toURL());
				_currentContainer.setImagePath(OfsFilesUtils.getPrefixedPathFromUrl(savedAsset.toClientURL(), _request, _t5AssetPrefix));
				_currentContainer.setWidth(savedImage.getWidth() > Sheet.WIDTH ? Sheet.WIDTH : savedImage.getWidth());
				_currentContainer.setHeight(savedImage.getHeight() > Sheet.HEIGHT ? Sheet.HEIGHT : savedImage.getHeight());
			} catch (ImageManipulationException e) {
				throw new RuntimeException(e.getMessage());
			}
		}
	}
	
	@OnEvent(value="success",component="textContainerEditForm")
	public Block saveContainerText() {
		_currentContainer.setText(Strings.isNullOrEmpty(_text)?"":_text);
		return _refresh;
	}
	
	// ~  ------------- Private Methods ----------------------
	private void loadContainer(String uid) {
		_currentContainer = _page.getContainer(uid);
	}
}
